package com.iscreen.dbupgrade.operations.mysql;

import com.iscreen.dbupgrade.constants.exceptions.DBUpgradeExceptionCodes;
import com.iscreen.dbupgrade.constants.schema.TableSchemaAudit;
import com.iscreen.dbupgrade.operations.OperationsHandler;
import com.iscreen.dbupgrade.operations.UpgradeOperation;
import com.iscreen.utils.db.query.Query;
import com.iscreen.utils.exceptions.ExceptionUtils;
import com.iscreen.utils.exceptions.IScreenException;

public class MySqlOperationsHandler extends OperationsHandler
{
	private final static String SQL_IS_OPERATION_DONE = "SELECT "
			+ TableSchemaAudit.FLD_STATUS + " FROM " + TableSchemaAudit.NAME
			+ " WHERE " + TableSchemaAudit.FLD_STEP_ID + " = ?" + " AND "
			+ TableSchemaAudit.FLD_COMMAND_ID + " = ?" + " AND "
			+ TableSchemaAudit.FLD_STATUS + " = '"
			+ TableSchemaAudit.STATUS_DONE + "'" + " LIMIT 1";

	private final static String SQL_INSERT_OPERATION = "INSERT INTO "
			+ TableSchemaAudit.NAME + "(" + TableSchemaAudit.FLD_STEP_ID + ","
			+ TableSchemaAudit.FLD_COMMAND_ID + ","
			+ TableSchemaAudit.FLD_OPERATION + "," + TableSchemaAudit.FLD_SQL
			+ "," + TableSchemaAudit.FLD_STATUS + ")" + " VALUES (?,?,?,?,?)";

	private final static String SQL_UPDATE_OPERATION_STATUS = "UPDATE "
			+ TableSchemaAudit.NAME + " SET " + TableSchemaAudit.FLD_STATUS
			+ " = ?, OPERATION = ? WHERE " + TableSchemaAudit.FLD_STEP_ID
			+ " = ?" + " AND " + TableSchemaAudit.FLD_COMMAND_ID + " = ?";

	@Override
	protected boolean isDone(UpgradeOperation operation)
			throws IScreenException
	{
		Query query = operation.getConnection().createQuery(
				SQL_IS_OPERATION_DONE);
		try
		{
			query.setParameter(1, operation.getStepId());
			query.setParameter(2, operation.getCommandId());
			query.open();
			if (query.next())
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		finally
		{
			query.close();
		}
	}

	protected void insertOperation(UpgradeOperation operation)
			throws IScreenException
	{

		Query query = operation.getConnection().createQuery(
				SQL_INSERT_OPERATION);

		try
		{
			query.setParameter(1, operation.getStepId());
			query.setParameter(2, operation.getCommandId());
			query.setParameter(3, operation.getOperation());
			query.setParameter(4, operation.getSql());
			query.setParameter(5, TableSchemaAudit.STATUS_START);
			query.execute();
		}
		finally
		{
			query.close();
		}
	}

	protected void updateOperationStatus(UpgradeOperation operation,
			String status) throws IScreenException
	{
		Query query = operation.getConnection().createQuery(
				SQL_UPDATE_OPERATION_STATUS);
		try
		{
			query.setParameter(1, status);
			query.setParameter(2, operation.getOperation());
			query.setParameter(3, operation.getStepId());
			query.setParameter(4, operation.getCommandId());
			int updateRecords = query.execute();
			if (updateRecords <= 0)
			{
				throw new IScreenException(
						DBUpgradeExceptionCodes.OPERATION_NOT_FOUND,
						"No operation to update");
			}

		}
		finally
		{
			query.close();
		}
	}

	@Override
	protected void markStart(UpgradeOperation operation)
			throws IScreenException
	{
		try
		{
			insertOperation(operation);
		}
		catch (IScreenException e)
		{
			if (ExceptionUtils.isDBDuplicateEntry(e))
			{
				updateOperationStatus(operation, TableSchemaAudit.STATUS_START);
			}
			else
			{
				throw e;
			}
		}

	}

	@Override
	protected void markDone(UpgradeOperation operation) throws IScreenException
	{
		updateOperationStatus(operation, TableSchemaAudit.STATUS_DONE);
	}

}
